<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Using Security with JPA</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/security-jpa" />
  <meta property="og:title" content="Quarkus - Using Security with JPA" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/security-jpa">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Using Security with JPA</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#architecture">Architecture</a></li>
<li><a href="#solution">Solution</a></li>
<li><a href="#creating-the-maven-project">Creating the Maven Project</a></li>
<li><a href="#writing-the-application">Writing the application</a>
<ul class="sectlevel2">
<li><a href="#defining-our-user-entity">Defining our user entity</a></li>
<li><a href="#configuring-the-application">Configuring the Application</a></li>
</ul>
</li>
<li><a href="#testing-the-application">Testing the Application</a></li>
<li><a href="#supported-model-types">Supported model types</a></li>
<li><a href="#storing-roles-in-another-entity">Storing roles in another entity</a></li>
<li><a href="#password-storage-and-hashing">Password storage and hashing</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This guide demonstrates how your Quarkus application can use a database to store your user identities with
<a href="hibernate-orm">Hibernate ORM</a> or <a href="hibernate-orm-panache">Hibernate ORM with Panache</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>less than 15 minutes</p>
</li>
<li>
<p>an IDE</p>
</li>
<li>
<p>JDK 1.8+ installed with <code>JAVA_HOME</code> configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="architecture"><a class="anchor" href="#architecture"></a>Architecture</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this example, we build a very simple microservice which offers three endpoints:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>/api/public</code></p>
</li>
<li>
<p><code>/api/users/me</code></p>
</li>
<li>
<p><code>/api/admin</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The <code>/api/public</code> endpoint can be accessed anonymously.
The <code>/api/admin</code> endpoint is protected with RBAC (Role-Based Access Control) where only users granted with the <code>admin</code> role can access. At this endpoint, we use the <code>@RolesAllowed</code> annotation to declaratively enforce the access constraint.
The <code>/api/users/me</code> endpoint is also protected with RBAC (Role-Based Access Control) where only users granted with the <code>user</code> role can access. As a response, it returns a JSON document with details about the user.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.</p>
</div>
<div class="paragraph">
<p>Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>security-jpa-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/security-jpa-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="creating-the-maven-project"><a class="anchor" href="#creating-the-maven-project"></a>Creating the Maven Project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First, we need a new project. Create a new project with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">mvn io.quarkus:quarkus-maven-plugin:1.7.0.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=security-jpa-quickstart \
    -Dextensions="security-jpa, jdbc-postgresql, resteasy, hibernate-orm-panache"
cd security-jpa-quickstart</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Don&#8217;t forget to add the database connector library of choice. Here we are using PostgreSQL as identity store.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This command generates a Maven project, importing the <code>security-jpa</code> extension
which allows you to map your security source to JPA entities.</p>
</div>
<div class="paragraph">
<p>If you already have your Quarkus project configured, you can add the <code>security-jpa</code> extension
to your project by running the following command in your project base directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="bash" class="language-bash hljs">./mvnw quarkus:add-extension -Dextensions="security-jpa"</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will add the following to your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-security-jpa&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="writing-the-application"><a class="anchor" href="#writing-the-application"></a>Writing the application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let&#8217;s start by implementing the <code>/api/public</code> endpoint. As you can see from the source code below, it is just a regular JAX-RS resource:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.jpa;

import javax.annotation.security.PermitAll;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/api/public")
public class PublicResource {

    @GET
    @PermitAll
    @Produces(MediaType.TEXT_PLAIN)
    public String publicResource() {
        return "public";
   }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The source code for the <code>/api/admin</code> endpoint is also very simple. The main difference here is that we are using a <code>@RolesAllowed</code> annotation to make sure that only users granted with the <code>admin</code> role can access the endpoint:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.jpa;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/api/admin")
public class AdminResource {

    @GET
    @RolesAllowed("admin")
    @Produces(MediaType.TEXT_PLAIN)
    public String adminResource() {
         return "admin";
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, let&#8217;s consider the <code>/api/users/me</code> endpoint. As you can see from the source code below, we are trusting only users with the <code>user</code> role.
We are using <code>SecurityContext</code> to get access to the current authenticated Principal and we return the user&#8217;s name. This information is loaded from the database.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.jpa;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;

@Path("/api/users")
public class UserResource {

    @GET
    @RolesAllowed("user")
    @Path("/me")
    @Produces(MediaType.APPLICATION_JSON)
    public String me(@Context SecurityContext securityContext) {
        return securityContext.getUserPrincipal().getName();
    }
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="defining-our-user-entity"><a class="anchor" href="#defining-our-user-entity"></a>Defining our user entity</h3>
<div class="paragraph">
<p>We can now describe how our security information is stored in our model by adding a few annotations to our <code>User</code> entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.jpa;

import javax.persistence.Entity;
import javax.persistence.Table;

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.security.common.BcryptUtil;
import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;

@Entity
@Table(name = "test_user")
@UserDefinition <i class="conum" data-value="1"></i><b>(1)</b>
public class User extends PanacheEntity {
    @Username <i class="conum" data-value="2"></i><b>(2)</b>
    public String username;
    @Password <i class="conum" data-value="3"></i><b>(3)</b>
    public String password;
    @Roles <i class="conum" data-value="4"></i><b>(4)</b>
    public String role;

    /**
     * Adds a new user in the database
     * @param username the user name
     * @param password the unencrypted password (it will be encrypted with bcrypt)
     * @param role the comma-separated roles
     */
    public static void add(String username, String password, String role) { <i class="conum" data-value="5"></i><b>(5)</b>
        User user = new User();
        user.username = username;
        user.password = BcryptUtil.bcryptHash(password);
        user.role = role;
        user.persist();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>security-jpa</code> extension is only initialized if there is a single entity annotated with <code>@UserDefinition</code>.</p>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This annotation must be present on a single entity. It can be a regular Hibernate ORM entity or a Hibernate ORM with Panache entity as in this example.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This indicates the field used for the user name.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>This indicates the field used for the password. This defaults to using bcrypt hashed passwords, but you can also configure it for clear text passwords.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>This indicates the comma-separated list of roles added to the target Principal representation attributes.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>This method allows us to add users while hashing the password with the proper bcrypt hash.</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="configuring-the-application"><a class="anchor" href="#configuring-the-application"></a>Configuring the Application</h3>
<div class="paragraph">
<p>The <code>security-jpa</code> extension requires at least one datasource to access to your database.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus
quarkus.datasource.password=quarkus
quarkus.datasource.jdbc.url=jdbc:postgresql:security_jpa

quarkus.hibernate-orm.database.generation=drop-and-create</code></pre>
</div>
</div>
<div class="paragraph">
<p>In our context, we are using PostgreSQL as identity store. The database schema is created by Hibernate ORM automatically
on startup (change this in production) and we initialise the database with users and roles in the <code>Startup</code> class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.jpa;

import javax.enterprise.event.Observes;
import javax.inject.Singleton;
import javax.transaction.Transactional;

import io.quarkus.runtime.StartupEvent;


@Singleton
public class Startup {
    @Transactional
    public void loadUsers(@Observes StartupEvent evt) {
        // reset and load all test users
        User.deleteAll();
        User.add("admin", "admin", "admin");
        User.add("user", "user", "user");
    }
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>It is probably useless but we kindly remind you that you must not store clear-text passwords in production environments ;-).
As a result, the <code>security-jpa</code> defaults to using bcrypt-hashed passwords.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="testing-the-application"><a class="anchor" href="#testing-the-application"></a>Testing the Application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The application is now protected and the identities are provided by our database.
The very first thing to check is to ensure the anonymous access works.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -i -X GET http://localhost:8080/api/public
HTTP/1.1 200 OK
Content-Length: 6
Content-Type: text/plain;charset=UTF-8

public%</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, let&#8217;s try a to hit a protected resource anonymously.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -i -X GET http://localhost:8080/api/admin
HTTP/1.1 401 Unauthorized
Content-Length: 14
Content-Type: text/html;charset=UTF-8

Not authorized%</code></pre>
</div>
</div>
<div class="paragraph">
<p>So far so good, now let&#8217;s try with an allowed user.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -i -X GET -u admin:admin http://localhost:8080/api/admin
HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain;charset=UTF-8

admin%</code></pre>
</div>
</div>
<div class="paragraph">
<p>By providing the <code>admin:admin</code> credentials, the extension authenticated the user and loaded their roles.
The <code>admin</code> user is authorized to access to the protected resources.</p>
</div>
<div class="paragraph">
<p>The user <code>admin</code> should be forbidden to access a resource protected with <code>@RolesAllowed("user")</code> because it doesn&#8217;t have this role.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -i -X GET -u admin:admin http://localhost:8080/api/users/me
HTTP/1.1 403 Forbidden
Content-Length: 34
Content-Type: text/html;charset=UTF-8

Forbidden%</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, using the user <code>user</code> works and the security context contains the principal details (username for instance).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl -i -X GET -u user:user http://localhost:8080/api/users/me
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain;charset=UTF-8

user%</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="supported-model-types"><a class="anchor" href="#supported-model-types"></a>Supported model types</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>The <code>@UserDefinition</code> class must be a JPA entity (with Panache or not).</p>
</li>
<li>
<p>The <code>@Username</code> and <code>@Password</code> field types must be of type <code>String</code>.</p>
</li>
<li>
<p>The <code>@Roles</code> field must either be of type <code>String</code> or <code>Collection&lt;String&gt;</code> or alternately a <code>Collection&lt;X&gt;</code> where <code>X</code> is an entity class with one <code>String</code> field annotated with the <code>@RolesValue</code> annotation.</p>
</li>
<li>
<p>Each <code>String</code> role element type will be parsed as a comma-separated list of roles.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="storing-roles-in-another-entity"><a class="anchor" href="#storing-roles-in-another-entity"></a>Storing roles in another entity</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can also store roles in another entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@UserDefinition
@Table(name = "test_user")
@Entity
public class User extends PanacheEntity {
    @Username
    public String name;

    @Password
    public String pass;

    @ManyToMany
    @Roles
    public List&lt;Role&gt; roles = new ArrayList&lt;&gt;();
}

@Entity
public class Role extends PanacheEntity {

    @ManyToMany(mappedBy = "roles")
    public List&lt;ExternalRolesUserEntity&gt; users;

    @RolesValue
    public String role;
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="password-storage-and-hashing"><a class="anchor" href="#password-storage-and-hashing"></a>Password storage and hashing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>By default, we consider passwords to be stored hashed with <a href="https://en.wikipedia.org/wiki/Bcrypt">bcrypt</a> under the
<a href="https://en.wikipedia.org/wiki/Crypt_&#169;">Modular Crypt Format</a> (MCF).</p>
</div>
<div class="paragraph">
<p>When you need to create such a hashed password we provide the convenient <code>String BcryptUtil.bcryptHash(String password)</code>
function, which defaults to creating a random salt and hashing in 10 iterations (though you can specify the iterations and salt
too).</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
with MCF you don&#8217;t need dedicated columns to store the hashing algo, the iterations count or the salt because
they&#8217;re all stored in the hashed value.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>WARN: you can also store passwords in clear text with <code>@Password(PasswordType.CLEAR)</code> but we strongly recommend against
it in production.</p>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
